﻿using Moq;
using SimpleInjector;
using Sustainalytics.Accounts.BusinessLogic;
using Sustainalytics.Accounts.Service.Auth;
using Sustainalytics.Accounts.Service.SignalRHub;
using Sustainalytics.AuthOperations;
using Sustainalytics.Controversies.BusinessLogic;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.MongoDB.Extensions;
using System.Collections.Generic;
using System.Configuration.Abstractions;
using System.Web.Http;


namespace Sustainalytics.Accounts.Service
{
    public static class CompositionRoot
    {
        private static readonly Dictionary<string, string> serviceBusParams = new Dictionary<string, string>
                {
                        { "ConnectionString", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.ConnectionString"] },
                        { "RegionEndpoint", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.RegionEndpoint"] },
                        { "SessionId", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.SessionId"] },
                        { "TopicPath", ConfigurationManager.Instance.AppSettings["Microsoft.ServiceBus.TopicPath"] },
                };

        public static Container RegisterDependencies(HttpConfiguration config)
        {
            var container = new Container();

            container.Options.DefaultScopedLifestyle = new SimpleInjector.Lifestyles.AsyncScopedLifestyle();
            container.RegisterWebApiControllers(config);

            var clientPlatformConnectionString = ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString;
            var clientlatformUrl = ConfigurationManager.Instance.AppSettings["clientPlatformUrl"];

            container.RegisterMisc(clientlatformUrl);

            container.RegisterRepositories(clientPlatformConnectionString);

            container.RegisterBussinessLogic(
                clientPlatformConnectionString);

            container.Verify();
            return container;
        }

        private static void RegisterRepositories(this Container container,
           string clientPlatformConnectionString)
        {
            container.Register(() => AccountsRepository.GetAccountsRepository(clientPlatformConnectionString));
            container.Register(typeof(Mock<IAccountsRepository>), () => new Mock<IAccountsRepository>());
            container.Register(typeof(IAccountsManagement), () => new AccountsManagement(container.GetInstance<IAccountsRepository>()));
            container.Register(() => MongoFactory.GetCollectionFromDatabase<AccountPermission>(clientPlatformConnectionString));
            container.Register(() => MongoFactory.GetCollectionFromDatabase<AccountProductCoverage>(clientPlatformConnectionString));
            container.Register(() => MongoFactory.GetCollectionFromDatabase<ReferenceUniverse>(MongoFactory.GetConnectionStrings().ClientDW));
        }

        private static void RegisterBussinessLogic(this Container container,
            string clientPlatformConnectionString)
        {
            container.Register(() => PlainBlFactory.GetInstance<User>(clientPlatformConnectionString));
            container.Register(() => PlainBlFactory.GetInstance<ClientUser>(clientPlatformConnectionString));
            container.Register(() => PlainBlFactory.GetInstance<AccountIpAuthentication>(clientPlatformConnectionString));
            container.Register(() => new Mock<IPlainBl<User>>());
            container.Register(() => new Mock<IPlainBl<ClientUser>>());
            container.Register(() => new Mock<IPlainBl<AccountIpAuthentication>>());
            container.Register(() => new Mock<IUserIpLoginManager>());
            container.Register(() => new Mock<IIpDataCheck>());

            container.Register(() => new AccountWithIpManager(
                container.GetInstance<IPlainBl<AccountIpAuthentication>>(),
                container.GetInstance<IUserIpLoginManager>(),
                container.GetInstance<IAccountsRepository>(),
                container.GetInstance<IIpDataCheck>()
            ));
            container.Register(typeof(IIpDataCheck), () => new IpDataCheck(
                container.GetInstance<IPlainBl<AccountIpAuthentication>>(),
                container.GetInstance<IPlainBl<User>>()));
            container.Register(typeof(IUserIpLoginManager), () => new UserIpLoginManager(
                container.GetInstance<IPlainBl<User>>(),
                container.GetInstance<IPlainBl<ClientUser>>()));
        }

        private static void RegisterMisc(
            this Container container, string clientlatformUrl)
        {
            container.Register(typeof(IAuthOperations), () => new AuthOperations.AuthOperations(
                 container.GetInstance<IAccountsRepository>(),
                 clientlatformUrl,
                 serviceBusParams));

            container.Register(() => AuthProvider.GetInstance(container.GetInstance<IAuthOperations>()));
            container.Register(() => UserLoginHubManager.Instance);
        }
    }
}
